package logic

import (
	"gitee.com/kristas/booting-go/gen_tool/booctl/creator"
	"gitee.com/kristas/booting-go/gen_tool/booctl/util"
	"os"
)

type Arr = []string

func UseCache() error {
	u := &creator.UsePluginFile{
		FileName:   "use_cache",
		Paths:      Arr{"gitee.com/kristas/booting-go/framework/cache"},
		Plugins:    Arr{"cache.NewStarter()"},
		Processors: nil,
	}
	config := creator.Properties{
		"application.cache.instance": "default",
	}
	cl := &creator.ConfigFile{
		Env:    "local",
		Config: config,
	}
	cp := &creator.ConfigFile{
		Env:    "prod",
		Config: config,
	}
	return creator.NewBatchCreator(u, cl, cp).Create()
}

func UseRedis() error {
	err := UseCache()
	if err != nil {
		return err
	}
	config := creator.Properties{
		"application.cache.instance": "redis",
		"application.redis.host":     "localhost:6379",
		"application.redis.username": "",
		"application.redis.password": "",
		"application.redis.db":       0,
	}
	cl := &creator.ConfigFile{
		Env:    "local",
		Config: config,
	}
	cp := &creator.ConfigFile{
		Env:    "prod",
		Config: config,
	}
	return creator.NewBatchCreator(cl, cp).Create()
}

func UseDatasource() error {
	// use datasource starter
	u := &creator.UsePluginFile{
		FileName:   "use_datasource",
		Paths:      Arr{"gitee.com/kristas/booting-go/framework/data/datasource"},
		Plugins:    Arr{"datasource.NewStarter()"},
		Processors: nil,
	}
	// create datasource config
	g := creator.NewGoFile("datasource_config", "config", "datasource_config", true)
	g.SetAttribute("DataSource", "application.datasource")

	// scan config
	sc := &creator.ScanFile{Path: "config"}

	// merge datasource config yaml
	config := creator.Properties{
		"application.datasource.url":      "tcp(localhost:3306)/{DB_NAME}?tls=skip-verify&charset=utf8&parseTime=true",
		"application.datasource.username": "root",
		"application.datasource.password": "root",
		"application.datasource.tunnel":   "tcp",
	}
	c := &creator.ConfigFile{
		Config: creator.Properties{
			"application.datasource.type":          "gorm.io/gorm",
			"application.datasource.driver":        "gorm.io/driver/mysql",
			"application.datasource.max_life_time": 120,
			"application.datasource.max_idle_conn": 10,
			"application.datasource.max_open_conn": 10,
			"application.datasource.lazy_fetch":    true,
		},
	}
	// merge config to config-local.yaml
	cl := &creator.ConfigFile{
		Env:    "local",
		Config: config,
	}

	// merge config to config-prod.yaml
	cp := &creator.ConfigFile{
		Env:    "prod",
		Config: config,
	}
	return creator.NewBatchCreator(u, g, sc, c, cl, cp).Create()
}

func UseGorm() error {
	u := &creator.UsePluginFile{
		FileName:     "use_gorm",
		Paths:        Arr{"gitee.com/kristas/booting-go/plugin/gorm_plugin"},
		Plugins:      Arr{"gorm_plugin.NewMySqlDriver()"},
		Processors:   nil,
		Dependencies: Arr{"gorm.io/gorm"},
	}
	c := &creator.ConfigFile{
		Config: creator.Properties{
			"gorm.skip_default_transaction":                      false,
			"gorm.naming_strategy.table_prefix":                  "",
			"gorm.naming_strategy.singular_table":                true,
			"gorm.full_save_associations":                        false,
			"gorm.dry_run":                                       false,
			"gorm.prepare_stmt":                                  true,
			"gorm.disable_automatic_ping":                        true,
			"gorm.disable_foreign_key_constraint_when_migrating": false,
			"gorm.disable_nested_transaction":                    false,
			"gorm.allow_global_update":                           false,
			"gorm.query_fields":                                  false,
			"gorm.create_batch_size":                             1000,
		},
	}
	o := creator.NewGoFile("orm_db", "/datasource", "gorm_db", true)
	return creator.NewBatchCreator(u, c, o).Create()
}

func UseIris() error {
	u := &creator.UsePluginFile{
		FileName:     "use_container",
		Paths:        Arr{"gitee.com/kristas/booting-go/plugin/iris_plugin"},
		Plugins:      Arr{"iris_plugin.NewStarter()"},
		Processors:   nil,
		Dependencies: Arr{"github.com/kataras/iris/v12"},
	}
	c := &creator.ConfigFile{
		Config: creator.Properties{
			"iris.FireMethodNotAllowed":              true,
			"iris.DisableBodyConsumptionOnUnmarshal": true,
			"iris.TimeFormat":                        "2006-01-02 15:04:05",
			"iris.Charset":                           "UTF-8",
			"iris.EnableOptimizations":               true,
		},
	}
	return creator.NewBatchCreator(u, c).Create()
}

func UseGin() error {
	u := &creator.UsePluginFile{
		FileName:     "use_container",
		Paths:        Arr{"gitee.com/kristas/booting-go/plugin/gin_plugin"},
		Plugins:      Arr{"gin_plugin.NewStarter()"},
		Processors:   nil,
		Dependencies: Arr{"github.com/gin-gonic/gin"},
	}
	defer cmd.FmtAll("init")
	return u.Create()
}

func UseEcho() error {
	u := &creator.UsePluginFile{
		FileName:     "use_container",
		Paths:        Arr{"gitee.com/kristas/booting-go/plugin/echo_plugin"},
		Plugins:      Arr{"echo_plugin.NewStarter()"},
		Processors:   nil,
		Dependencies: Arr{"github.com/labstack/echo/v4"},
	}
	return u.Create()
}

func UseSecurity() error {
	sc := creator.NewGoFile("security_config", "config", "", true)
	u := &creator.UsePluginFile{
		FileName: "use_security",
		Paths: Arr{
			"gitee.com/kristas/booting-go/framework/security",
			"gitee.com/kristas/booting-go/plugin/casbin_plugin",
		},
		Plugins: Arr{
			"casbin_plugin.NewFilter(config.GetRoleHandler)",
			"security.NewStarter()",
		},
		Packages: Arr{
			"config",
		},
		Processors: nil,
	}
	g := creator.NewGoFile("datasource_config", "config", "auth_datasource_config", true)
	g.SetAttribute("DataSource", "casbin.datasource")
	c := &creator.ConfigFile{
		Config: creator.Properties{
			"casbin.model.request_definition": "r = user, url, method",
			"casbin.model.policy_definition":  "p = user, url, method",
			"casbin.model.role_definition":    "g = _, _",
			"casbin.model.policy_effect":      "e = some(where (p.eft == allow))",
			"casbin.model.matchers":           "m = g(r.user, p.user) && keyMatch2(r.url, p.url) && regexMatch(r.method, p.method) || r.user=='root'",
			"casbin.datasource.type":          "gorm.io/gorm",
			"casbin.datasource.driver":        "gorm.io/driver/mysql",
			"casbin.datasource.max_life_time": 120,
			"casbin.datasource.max_idle_conn": 10,
			"casbin.datasource.max_open_conn": 10,
			"casbin.datasource.lazy_fetch":    true,
		},
	}
	config := creator.Properties{
		"casbin.datasource.url":      "tcp(localhost:3306)/{DB_NAME}?tls=skip-verify&charset=utf8&parseTime=true",
		"casbin.datasource.username": "root",
		"casbin.datasource.password": "root",
		"casbin.datasource.tunnel":   "tcp",
	}

	// merge config to config-local.yaml
	cl := &creator.ConfigFile{
		Env:    "local",
		Config: config,
	}

	// merge config to config-prod.yaml
	cp := &creator.ConfigFile{
		Env:    "prod",
		Config: config,
	}

	return creator.NewBatchCreator(sc, u, g, c, cl, cp).Create()
}

func UseSwagger() error {
	err := util.CloneSrc("./resources", "https://gitee.com/kristas/swagger-ui.git")
	if err != nil {
		return err
	}
	if util.FileExist("./resources/swagger-ui/.git") {
		os.RemoveAll("./resources/swagger-ui/.git")
	}
	u := &creator.UsePluginFile{
		FileName:   "use_swagger",
		Paths:      Arr{"gitee.com/kristas/booting-go/plugin/swagger_plugin"},
		Plugins:    Arr{"swagger_plugin.NewStarter()"},
		Processors: nil,
	}
	c := creator.NewGoFile("open_api_config", "config", "", true)
	s := &creator.ScanFile{
		Path: "config",
	}
	return creator.NewBatchCreator(c, u, s).Create()
}

func UseWebsocket() error {
	u := &creator.UsePluginFile{
		FileName:   "use_websocket",
		Paths:      Arr{"gitee.com/kristas/booting-go/plugin/websocket_plugin"},
		Plugins:    Arr{"websocket_plugin.NewStarter()"},
		Processors: nil,
	}
	c := &creator.ConfigFile{
		Config: creator.Properties{
			"websocket.write_wait":         "10s",
			"websocket.pong_wait":          "60s",
			"websocket.ping_period":        "10s",
			"websocket.close_grace_period": "10s",
			"websocket.max_message_size":   8192,
			"websocket.check_origin":       false,
		},
	}
	return creator.NewBatchCreator(u, c).Create()
}

func UseOpenBrowserPlugin(url string) error {
	u := &creator.UsePluginFile{
		FileName:   "use_open_browser",
		Paths:      Arr{"gitee.com/kristas/booting-go/plugin/open_browser_plugin"},
		Plugins:    Arr{`open_browser_plugin.NewRunner()`},
		Processors: nil,
	}
	c := &creator.ConfigFile{
		Env: "local",
		Config: creator.Properties{
			"open_browser.enable": true,
			"open_browser.url":    "http://localhost:${server.port}" + url,
		},
		Overwrite: false,
	}
	return creator.NewBatchCreator(u, c).Create()
}

func UseFlywayPlugin() error {
	u := &creator.UsePluginFile{
		FileName:   "use_flyway",
		Paths:      Arr{"gitee.com/kristas/booting-go/plugin/flyway_plugin"},
		Plugins:    Arr{"flyway_plugin.NewFlywayStarter()"},
		Processors: nil,
	}
	c := &creator.ConfigFile{
		Config: creator.Properties{
			"application.flyway.enable":    true,
			"application.flyway.locations": "migrations",
		},
	}
	err := util.MkDir("migrations")
	if err != nil {
		return err
	}
	return creator.NewBatchCreator(u, c).Create()
}
